package cn.cloudtogo.adaptation.listener;

import cn.cloudtogo.adaptation.amqp.ExternalRabbitmqProperties;
import cn.cloudtogo.adaptation.amqp.Message;
import cn.cloudtogo.adaptation.amqp.MessageConverter;
import cn.cloudtogo.adaptation.amqp.RabbitmqConfiguration;
import cn.cloudtogo.adaptation.amqp.ironegg.MiddlewareChangeType;
import cn.cloudtogo.adaptation.amqp.ironegg.MiddlewareMessageBody;
import cn.cloudtogo.adaptation.amqp.ironegg.MiddlewareRawData;
import cn.cloudtogo.common.DatasourceDeleteService;
import cn.cloudtogo.common.DatasourcePutService;
import cn.cloudtogo.common.model.DatasourceTypes;
import cn.cloudtogo.common.types.ConnectString;
import cn.cloudtogo.common.types.Credential;
import cn.cloudtogo.common.types.Endpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

import java.util.Objects;

/**
 * @author yaolianhua789@gmail.com
 **/
@Component
@ConditionalOnProperty(value = ExternalRabbitmqProperties.LISTENER_ENABLED, havingValue = "true")
@Slf4j
public class StarOSMiddlewareEventListener {

    private final DatasourcePutService datasourcePutService;
    private final DatasourceDeleteService datasourceDeleteService;
    private final MessageConverter messageConverter;

    public StarOSMiddlewareEventListener(DatasourcePutService datasourcePutService,
                                         DatasourceDeleteService datasourceDeleteService,
                                         MessageConverter messageConverter) {
        this.datasourcePutService = datasourcePutService;
        this.datasourceDeleteService = datasourceDeleteService;
        this.messageConverter = messageConverter;
    }

    @RabbitListener(
            bindings = {
                    @QueueBinding(
                            value = @Queue(name = RabbitmqConfiguration.QUEUE_MIDDLEWARE_UPDATE),
                            exchange = @Exchange(type = ExchangeTypes.FANOUT, value = RabbitmqConfiguration.EXCHANGE_IRONEGG_SPECIFIC_CHANGE)
                    )
            }
    )
    @Async
    public void mysqlMiddlewareUpdateEvent(String content) {

        try {
            Message<MiddlewareMessageBody> message = messageConverter.convertMiddlewareMessageBody(content);
            if (message == null) {
                return;
            }
            String changeType = message.getData().getChangeType();
            if (!Objects.equals(changeType, MiddlewareChangeType.UPDATE.name())) {
                return;
            }
            log.info("[StarOS middleware [{}] change event received] \n {}", changeType, content);

            MiddlewareRawData origin = message.getData().getOrigin();
            MiddlewareRawData target = message.getData().getTarget();

            if (!Objects.equals(origin.getMiddlewareType(), target.getMiddlewareType())) {
                log.warn("middleware type inconsistent for both data");
                return;
            }
            String openid = message.getData().getId();
            if (ConnectString.MYSQL.equalsIgnoreCase(origin.getMiddlewareType())) {
                String host = target.getMetadata().getHost();
                String port = target.getMetadata().getPort();
                String username = target.getMetadata().getUsername();
                String password = target.getMetadata().getPassword();
                String schema = target.getMetadata().getSchemaName();

                ConnectString connectString = new ConnectString(DatasourceTypes.Mysql,
                        Credential.of(username, password),
                        Endpoint.of(host, Integer.parseInt(port)),
                        schema);
                String connectionString = ConnectString.constructUrl(connectString);

                datasourcePutService.updateConnectionInfoByOpenid(openid, connectionString);
            }


        } catch (Exception e) {
            log.error("StarOS middleware event listener error. {}", e.getMessage(), e);
        }

    }

    @RabbitListener(
            bindings = {
                    @QueueBinding(
                            value = @Queue(name = RabbitmqConfiguration.QUEUE_MIDDLEWARE_DELETE),
                            exchange = @Exchange(type = ExchangeTypes.FANOUT, value = RabbitmqConfiguration.EXCHANGE_IRONEGG_SPECIFIC_CHANGE)
                    )
            }
    )
    @Async
    public void mysqlMiddlewareDeleteEvent(String content) {

        try {
            Message<MiddlewareMessageBody> message = messageConverter.convertMiddlewareMessageBody(content);
            if (message == null) {
                return;
            }
            String changeType = message.getData().getChangeType();
            if (!Objects.equals(changeType, MiddlewareChangeType.DELETE.name())) {
                return;
            }
            log.info("[StarOS middleware [{}] change event received] \n {}", changeType, content);

            String openid = message.getData().getId();

            datasourceDeleteService.deletes(openid);
        } catch (Exception e) {
            log.error("StarOS middleware event listener error. {}", e.getMessage(), e);
        }

    }

}
